import { UNIT_BAJ_ATTR_CONFIG, indexOfBinAttrKey } from "../config/UnitFieldConfig";
import {  AttrChangeEnum, DmgType, EventType, KeyUnitStatB, KeyUnitStatHpMpKey, Status, UnitAttr, UnitAttrStruct, XAbilityTrgType } from "../types/L_Type";
import L_AttrControlUtil from "../utils/L_AttrControlUtil";
import L_String from "../utils/L_String";
import UnitAttrChangeEx from "../module/unit_field_change/UnitAttrChangeEx";
import EnvConfig from "../config/EnvConfig";
import { AdditDmgEffTypeKey } from "../config/AdditDmgEffectConfig";
import IDGen from "../utils/IDGen";
import EventX from "../event/eventdef/EventX";
import { XAbilityAttr, XAbilityConfig, XAbilityTypeKey } from "../config/XAbilityConfig";


/** 单位增强类 绑定单位的所有额外属性 */
export default class UnitX{

  unitXId:number //自管理的id 方便某些情况的比对关联等

  unit:unit;  //对象句柄 CreateUnit方法的返回值

  handle:number;  //指针地址 GetHandleId(u) 的值

  name:string;
  
  lvl: number;


  private _pSkill?: string[];

  private _aSkill?: string[];

  private _attrs?: UnitAttr;

  private _dtRes?: DmgType;

  private _dtEnh?: DmgType;

  private _additDmgEffs?: Array<AdditDmgEffTypeKey> //单位拥有的附加攻击特效  AdditDmgEffType

  private _unitXAbilityMap?: Map<XAbilityTrgType,Array<XAbilityTypeKey>> //单位拥有的特殊触发能力

  private _eventMap?: Map<EventType, Map<number, EventX>> //单位拥有的dot  buff等map集合  number指事件id

  private _status?:Map<Status,number>  //单位拥有的状态计数   方便某些情况的使用

 
  constructor(unit:any,handle:number,name:string,lvl:number,initFields?:UnitAttrStruct){
    this.unit=unit;
    this.handle=handle;
    this.name=name//GetUnitName(unit);      
    this.lvl= lvl
    this.unitXId=IDGen.getNextId('UNITX')
    if(initFields!=undefined){
      //刷新一下单位初始的属性
       console.log("--->unix初始化属性",initFields)
      this.changeUnitAttrs(initFields,AttrChangeEnum.INCREASE)
       console.log("--->unix初始化属性完成")
    }
  }

 /**
  * 增加单位的属性
  * @param incrAttrs  增加的属性对象
  * @param mulVal 增加属性的倍率  注意!只能传递整数  在某些特殊需求时可能会使用 （奖励X倍属性）
  */
  public  incrUnitAttrs(incrAttrs:UnitAttrStruct,mulVal?:number){
    this.changeUnitAttrs(incrAttrs,AttrChangeEnum.INCREASE,mulVal)
  }

   /**
  * 减少单位的属性
  * @param redcAttrs  减少的属性对象
  */
  public  redcUnitAttrs(redcAttrs:UnitAttrStruct){
    this.changeUnitAttrs(redcAttrs,AttrChangeEnum.REDUCE)
  }


  /**
   * 改变单位属性
   * @param incrAttrs 改变属性对象
   * @param incType 增加|减少枚举
   * @param mulVal incrAttrs属性的增加倍率 方便某些情况的处理 (整数倍率)
   * @returns 
   */
  private  changeUnitAttrs(incrAttrs:UnitAttrStruct,incType:AttrChangeEnum,mulVal?:number){
    if(incrAttrs==null) return
    //增加还是减少符号位修正
    let fix=(incType==AttrChangeEnum.INCREASE?1:-1)*(mulVal || 1)
    //1.第一类 二进制属性+自定义基础属性
    if(incrAttrs.attrs!=undefined){
        //先直接修改ux对象  合并属性
        L_AttrControlUtil.mergeField(this.attrs,incrAttrs.attrs,incType,mulVal);
        //遍历改变的值 进行API调用
        for(let k in incrAttrs.attrs){
            if(k==UNIT_BAJ_ATTR_CONFIG.hp.key || k==UNIT_BAJ_ATTR_CONFIG.mp.key ){
                //生命 魔法改变 直接改变值  不用同步ux对象
                if(!EnvConfig.devMod){
                  UnitAttrChangeEx.incUnitStatHpMp(this.unit,k as KeyUnitStatHpMpKey,fix*(incrAttrs.attrs as any)[k])
                }
                console.log("hp|mp属性改变:",k,",",fix*(incrAttrs.attrs as any)[k])
            }else if(indexOfBinAttrKey(k)){
                //其他二进制属性改变  直接使用ux合并后的数值作为最终值  
                if(!EnvConfig.devMod){
                  UnitAttrChangeEx.setUnitStatB(this.unit,k as KeyUnitStatB,(this.attrs as any)[k])
                }
                console.log("binary属性改变:",k,",",fix*(incrAttrs.attrs as any)[k])
            }else{
                //TODO 非二进制属性改变  韧性，暴击等自定义属性
                console.log("属性改变:",k,",",fix*(incrAttrs.attrs as any)[k])
            }
        }
    }
    //2.第二类元素增强
    if(incrAttrs.dtEnh!=undefined){
        L_AttrControlUtil.mergeField(this.dtEnh,incrAttrs.dtEnh,incType,mulVal)
    }
    //3.第三类元素抗性
    if(incrAttrs.dtRes!=undefined){
        L_AttrControlUtil.mergeField(this.dtRes,incrAttrs.dtRes,incType,mulVal)
    }

}  
  
  
    

    public get pSkill(): string[] | undefined {
      return this._pSkill;
    }
    public set pSkill(value: string[] | undefined) {
      this._pSkill = value;
    }

    public get aSkill(): string[] | undefined {
      return this._aSkill;
    }
    public set aSkill(value: string[] | undefined) {
      this._aSkill = value;
    }

    public get attrs(): UnitAttr | undefined {
      if(this._attrs==undefined) this._attrs={}
      return this._attrs;
    }
    public set attrs(value: UnitAttr | undefined) {
      this._attrs = value;
    }

    public get dtRes(): DmgType | undefined {
      if(this._dtRes==undefined) this._dtRes={}
      return this._dtRes;
    }
    public set dtRes(value: DmgType | undefined) {
      this._dtRes = value;
    }

    public get dtEnh(): DmgType | undefined {
      if(this._dtEnh==undefined) this._dtEnh={}
      return this._dtEnh;
    }
    public set dtEnh(value: DmgType | undefined) {
      this._dtEnh = value;
    }

    

    public get additDmgEffs(): Array<AdditDmgEffTypeKey> | undefined  {
      return this._additDmgEffs;
    }
    public additDmgEffAddX(addDmgEffKey:AdditDmgEffTypeKey) {
      console.log("单位获取攻击特效:",addDmgEffKey)
      if(this._additDmgEffs==undefined) this._additDmgEffs=[]
      this._additDmgEffs.push(addDmgEffKey)
    }
    public  additDmgEffRemoveX(addDmgEffKey:AdditDmgEffTypeKey) {
      let index=this._additDmgEffs?.indexOf(addDmgEffKey)
      if(index!=undefined && index!=-1){
        this._additDmgEffs?.splice(index,1)
      }
    }

    

    public getEventTypeMap(eventType:EventType):Map<number,EventX> | undefined {
      // if(this._eventMap==undefined){
      //   this._eventMap=new Map()
      // }
      // let rsMap=this._eventMap.get(eventType)
      // if(rsMap==undefined){
      //   rsMap=new Map()
      //   this._eventMap.set(eventType,rsMap)
      // }

      return this._eventMap?.get(eventType);
    }


    public eventTypeMapAddx(eventType:EventType,e:EventX):void{
      if(this._eventMap==undefined){
        this._eventMap=new Map()
      }
      let rsMap=this._eventMap.get(eventType)
      if(rsMap==undefined){
        rsMap=new Map()
        rsMap.set(e.eventId,e)
        this._eventMap.set(eventType,rsMap)
      }else{
        rsMap.set(e.eventId,e)
      }
      //if(eventType=='BT_CASTING')console.log("eventTypeMapAddx(),",this._eventMap)
    }

    public eventTypeMapRemovex(eventType:EventType,e:EventX):void{
      this._eventMap?.get(eventType)?.delete(e.eventId)
      //if(eventType=='BT_CASTING')console.log("eventTypeMapRemovex(),",this._eventMap)
    }


    public  xAbilitysTrgTypeArr(trgTypeKey:XAbilityTrgType): Array<XAbilityTypeKey> | undefined {
      return this._unitXAbilityMap?.get(trgTypeKey);
    }

    public xAbilitysAddX(xAbilityTypeKey:XAbilityTypeKey) {
      console.log("单位获取能力:",xAbilityTypeKey)
      let trgTypeKey:XAbilityTrgType=((XAbilityConfig as any)[xAbilityTypeKey] as XAbilityAttr).trgType

      if(this._unitXAbilityMap==undefined) this._unitXAbilityMap=new Map()
      let tmp=this._unitXAbilityMap.get(trgTypeKey) 
      if(tmp==undefined){
        this._unitXAbilityMap.set(trgTypeKey,[xAbilityTypeKey])
      }else{
        tmp.push(xAbilityTypeKey)
      }
    }
    public  xAbilitysRemoveX(xAbilityTypeKey:XAbilityTypeKey) {
      let trgTypeKey:XAbilityTrgType=((XAbilityConfig as any)[xAbilityTypeKey] as XAbilityAttr).trgType
      let index=this._unitXAbilityMap?.get(trgTypeKey)?.indexOf(xAbilityTypeKey)
      if(index!=undefined &&  index!=-1){
        this._unitXAbilityMap?.get(trgTypeKey)?.splice(index,1)
      }
    }

    public statusAddX(status:Status) {
      if(this._status==undefined) this._status=new Map()
      let n=this._status.get(status) 
      if(n==undefined){
        this._status.set(status,1)
      }else{
        this._status.set(status,(n+1))
      }
    }
    public  statusRemoveX(status:Status) {
      let n=this._status?.get(status)
      if(n!=undefined){
        this._status?.set(status,(n-1))
      }
    }
    public  statusExist(status:Status):boolean {
      return (this._status?.get(status) || 0)>0
    }


    public getUnitSkillLvl(skillIdStr:string){
      //TODOTODO 实现单位技能等级管理
      return 1
    }

}  